/*!
 * Core module v1.0.0 of jRaiser javascript library
 * http://code.google.com/p/jraiser/
 *
 * Author: Heero.Luo
 * Licensed under MIT license
 *
 * Date: Wed May 30 2012 15:40:51 GMT+0800
 */
define(function(require, exports, module) { 'use strict';

/* 两个常用的ES5原生方法 */
if (!String.prototype.trim) {
	var ws = '[\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF]+';
	var trimBeginRegexp = new RegExp('^' + ws),
        trimEndRegexp = new RegExp(ws + '$');
		
    String.prototype.trim = function() {
		return String(this).replace(trimBeginRegexp, '').replace(trimEndRegexp, '');
    };
}

if (!Array.prototype.forEach) {
	Array.prototype.forEach = function(fn, thisp) {
		var i = -1, length = this.length >>> 0;

		while (++i < length) {
			if (i in this) {
				fn.call(thisp, this[i], i, this);
			}
		}
    };
}


/**
 * 把源对象的属性扩展到目标对象
 * !!! 当target为空时，此函数不会默认创建一个对象作为target，而是抛出异常
 * @param {Mixed} 目标对象
 * @param {Mixed*} 若干个源对象
 * @return {Mixed} 目标对象
 */
function extend(target) {
	if (!target) { throw new Error('target cannot be null'); }

	var i = 0, len = arguments.length, p, src;
	while (++i < len) {
		src = arguments[i];
		if (src) {
			for (p in src) { target[p] = src[p]; }
		}
	}
	
	return target;
}


// 用于对比某变量的值是否undefined
var undefined;
// 基本类型判断
var toString = Object.prototype.toString;

/**
 * 检查变量是否Function类型
 * @param {Mixed} 待测变量
 * @return {Boolean} 待测变量是否Function类型
 */
function isFunction(value) { return toString.call(value) === '[object Function]'; }


/**
 * Get First, Set All 访问器
 * @param {Mixed} 访问对象
 * @param {String|Mixed} 访问键名，如果为Object类型，则以对象的每个属性和值递归调用此函数
 * @param {Mixed} 访问值，如果为undefined，则为get first操作，否则为set all操作
 * @param {Boolean} 当value为函数时，是否执行函数并以函数返回值作为最终值
 * @param {Object} 访问函数，包括：
 *   get(firstElement, key): get first操作函数，this指向访问对象
 *   set(currentElement, key, value): set all操作函数，this指向访问对象
 * @return {Mixed} get first操作返回键名对应的值；set all操作返回访问对象
 */
function access(elems, key, value, isExec, fns) {
	var len = elems.length, i, temp;
	
	if (key != null && typeof key === 'object') {
		for (var k in key) {
			access(elems, k, key[k], isExec, fns);
		}
		return elems;
	}

	if (value !== undefined) {
		isExec = isExec && isFunction(value);

		i = -1;
		while (++i < len) {
			fns.set.call(elems, elems[i], key, isExec ?
				value.call(elems[i], fns.get.call(elems, elems[i], key), i) : value );
		}
	
		return elems;
	}

	return len ? fns.get.call(elems, elems[0], key) : null;
}


extend(exports, {
	/**
	 * 检查变量是否Array类型
	 * @param {Mixed} 待测变量
	 * @return {Boolean} 待测变量是否Array类型
	 */
	isArray : Array.isArray || function(value) { return toString.call(value) === '[object Array]'; },

	/**
	 * See line 63
	 */
	isFunction : isFunction,

	/**
	 * 检查变量是否Date类型
	 * @param {Mixed} 待测变量
	 * @return {Boolean} 待测变量是否Date类型
	 */
	isDate : function(value) { return toString.call(value) === '[object Date]'; },

	/**
	 * 检查变量是否Object
	 * @param {Mixed} 待测变量
     * @return {Boolean} 待测变量是否Object
	 */
	isObject : function(value) { return toString.call(value) === '[object Object]'; },
	
	/**
	 * 检查对象是否空Object
	 * @param {Object} 待测对象
     * @return {Boolean} 待测对象是否空Object
	 */
	isEmptyObject : function(obj) {
		for (var i in obj) { return false; }
		return true;
	},
	
	/**
	 * 检查变量的值是否undefined
	 * @param {Mixed} 待测变量
     * @return {Boolean} 待测变量的值是否undefined
	 */
	isUndefined : function(value) { return value === undefined; },

	/**
	 * See line 36
	 */
	extend : extend,

	/**
	 * 把源对象的属性扩展到目标对象
	 * @param {Mixed} 目标对象
	 * @param {Mixed} 源对象
	 * @param {Object} 选项
	 *   isOverWhite {Boolean} (Optional) 是否覆盖目标对象的同名属性，默认为false
	 *   whiteList {Array<String>} (Optional) 扩展属性白名单
	 * @return {Mixed} 目标对象
	 */
	mix : function(target, source, opts) {
		if (source != null) {
			opts = opts || { };
		
			if (opts.whiteList) {
				opts.whiteList.forEach(function(val) {
					if ( val in source && ( opts.isOverwrite || !(val in target) ) ) {
						target[val] = source[val];
					}
				});
			} else {
				for (var i in source) {
					if ( opts.isOverwrite || !(i in target) ) {
						target[i] = source[i];	
					}
				}
			}
		}

		return target;
	},
	
	/**
	 * 对指定对象的每个元素执行指定函数
	 * @param {Mixed} 遍历对象
	 * @param {Function} 操作函数，原型为callback(value, key, obj)
	 *   当函数返回值为false时，遍历中断
	 *   !!! 与jQuery不同，操作函数的第一个参数是值，第二个参数是键名
	 * @return {Mixed} 遍历对象
	 */
	each : function(obj, callback) {
		if (obj != null) {
			var i = -1, len = obj.length;
			if ( len === undefined || isFunction(obj) ) {
				for (i in obj) {
					if ( false === callback.call(obj[i], obj[i], i, obj) ) {
						break;
					}
				}
			} else {
				while (++i < len) {
					if ( false === callback.call(obj[i], obj[i], i, obj) ) {
						break;
					}
				}
			}
		}
		
		return obj;
	},

	/**
	 * 把数组或类数组中的元素复制到新数组中
	 * @param {Array|ArrayLike} 数组或类数组
	 * @return {Array} 新数组
	 */
	toArray : function(obj) {
		var arr;
		try {
			arr = Array.prototype.slice.call(obj);
		} catch (e) {
			arr = [ ];
			var i = obj.length;
			while (i) {
				arr[--i] = obj[i];
			}
		}
		return arr;
	},
	
	/**
	 * 创建类
	 * @param {Function} 构造函数
	 * @param {Object} 方法
	 * @param {Object} 父类
	 * @param {Function|Array} 传递给父类的参数，默认与子类构造函数参数一致
	 * @return {Function} 类
	 */
	newClass : function(factory, methods, parent, parentArgs) {
		methods && extend(factory.prototype, methods);
		return parent ? this.inherit(factory, parent, parentArgs) : factory;
	},
	
	/**
	 * 继承类
	 * @param {Function} 子类
	 * @param {Function} 父类
	 * @param {Function|Array} 指定传递给父类的参数，默认与子类构造函数参数一致
	 * @return {Function} 继承后的子类
	 */
	inherit : function(sub, parent, parentArgs) {
		var trueClass = parentArgs ? function() {
			parent.apply(this, isFunction(parentArgs) ? parentArgs.apply(this, arguments) : parentArgs);
			sub.apply(this, arguments);
		} : function() {
			parent.apply(this, arguments);
			sub.apply(this, arguments);
		};
		
		extend(trueClass.prototype, parent.prototype, sub.prototype);
		
		// 记录父类
		trueClass.parentClass = parent;
		// 记录超类
		trueClass.superClass = parent.superClass || parent;

		return trueClass;
	},
	
	/**
	 * See line 71
	 */
	access : access
});

});